home *** CD-ROM | disk | FTP | other *** search
/ Scene Storm / Scene Storm - Volume 1.iso / coding / c / lha_axeman / lhext.c < prev    next >
C/C++ Source or Header  |  1995-09-01  |  6KB  |  304 lines

  1. /*----------------------------------------------------------------------*/
  2. /*            LHarc Extract Command                */
  3. /*        This is part of LHarc UNIX Archiver Driver        */
  4. /*                                    */
  5. /*        Copyright(C) MCMLXXXIX  Yooichi.Tagawa            */
  6. /*                                    */
  7. /*  V0.00  Original                1988.05.23  Y.Tagawa    */
  8. /*  V1.00  Fixed                1989.09.22  Y.Tagawa    */
  9. /*  V0.03  LHa for UNIX                1991.12.17  M.Oki    */
  10. /*----------------------------------------------------------------------*/
  11.  
  12. #include "lharc.h"
  13.  
  14. extern int decode_lzhuf ();
  15.  
  16. static boolean inquire_extract(char *name)
  17. {
  18.   struct stat stbuf;
  19.  
  20.   if(stat (name, &stbuf) >= 0)
  21.   {
  22.     if(!is_regularfile (&stbuf))
  23.       {
  24.         error ("Already exist (not a file)", name);
  25.         return FALSE;
  26.       }
  27.  
  28.     if(noexec)
  29.       {
  30.         printf ("EXTRACT %s but file is exist.\n", name);
  31.         return FALSE;
  32.       }
  33.     else if(!force)
  34.       {
  35.         if(!isatty(0)) return FALSE;
  36.         switch (inquire("OverWrite ?(Yes/No/All)", name, "YyNnAa"))
  37.         {
  38.           case 0:
  39.           case 1:        /* Y/y */
  40.             break;
  41.           case 2:
  42.           case 3:        /* N/n */
  43.             return FALSE;
  44.           case 4:
  45.           case 5:        /* A/a */
  46.             force = TRUE;
  47.             break;
  48.        }
  49.       }
  50.   }
  51.  
  52.   if(noexec) printf ("EXTRACT %s\n", name);
  53.   return TRUE;
  54. }
  55.  
  56. static boolean make_parent_path(char *name)
  57. {
  58.   char path[FILENAME_LENGTH];
  59.   struct stat stbuf;
  60.   register char *p;
  61.  
  62.   /* make parent directory name into PATH for recursive call */
  63.   strcpy (path, name);
  64.   for(p = path + strlen (path); p > path; p--)
  65.     if(p[-1] == '/')
  66.     {
  67.         *--p = '\0';
  68.         break;
  69.     }
  70.  
  71.     if(p == path)
  72.     {
  73.       message("Why?", "ROOT");
  74.       return FALSE;            /* no more parent. */
  75.     }
  76.  
  77.     if(stat(path, &stbuf) >= 0)
  78.     {
  79.       if(is_directory (&stbuf))    return TRUE;
  80.       error ("Not a directory", path);
  81.       return FALSE;
  82.     }
  83.     errno = 0;
  84.  
  85.     if(verbose) printf("Making directory \"%s\".", path);
  86.  
  87.     if(mkdir(path, 0777) >= 0)/* try */
  88.       return TRUE;            /* successful done. */
  89.     errno = 0;
  90.  
  91.     if(!make_parent_path(path))
  92.       return FALSE;
  93.  
  94.     if(mkdir(path, 0777) < 0)    /* try again */
  95.     {
  96.       message("Cannot make directory", path);
  97.       return FALSE;
  98.     }
  99.  
  100.   return TRUE;
  101. }
  102.  
  103. static FILE *open_with_make_path(char *name)
  104. {
  105.   FILE *fp;
  106.  
  107.   if((fp = fopen(name, WRITE_BINARY)) == NULL)
  108.   {
  109.     errno = 0;
  110.     if(!make_parent_path (name) || (fp = fopen (name, WRITE_BINARY)) == NULL)
  111.         error("Cannot extract", name);
  112.     errno = 0;
  113.   }
  114.   return fp;
  115. }
  116.  
  117. static void adjust_info(char *name, LzHeader *hdr)
  118. {
  119. }
  120.  
  121. static char *methods[10] =
  122. {
  123.     "-lh0-", "-lh1-", "-lh2-", "-lh3-", "-lh4-",
  124.     "-lh5-", "-lzs-", "-lz5-", "-lz4-", NULL
  125. };
  126.  
  127. static void extract_one(FILE *afp, LzHeader *hdr)
  128. {
  129.   FILE *fp;                    /* output file */
  130.   char name[257];
  131.   int crc;
  132.   int method;
  133.   boolean save_quiet, save_verbose;
  134.   char *q = hdr->name , c;
  135.  
  136.   if( ignore_directory && rindex(hdr->name,'/') )
  137.   {
  138.     q = (char *)rindex(hdr->name,'/') + 1;
  139.   }
  140.   else
  141.   {
  142.     if(*q=='/')
  143.       {
  144.         q++;
  145.         /*
  146.          *    if OSK then strip device name
  147.          */
  148.         if(hdr->extend_type == EXTEND_OS68K || hdr->extend_type == EXTEND_XOSK )
  149.           {
  150.             do c=(*q++); while( c && c!='/' );
  151.             if(!c||!*q) q = ".";    /* if device name only */
  152.           }
  153.       }
  154.   }
  155.  
  156.   if(extract_directory)
  157.     sprintf(name, "%s/%s", extract_directory, q);
  158.   else
  159.     strcpy(name, q);
  160.  
  161.   if((hdr->unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_REGULAR)
  162.   {
  163.     for(method = 0; ; method++)
  164.       {
  165.         if(methods[method] == NULL)
  166.         {
  167.           error("Unknown method skiped ...", name);
  168.           return;
  169.         }
  170.         if(bcmp(hdr->method, methods[method], 5) == 0)
  171.           break;
  172.       }
  173.  
  174.     reading_filename = archive_name;
  175.     writting_filename = name;
  176.     if(output_to_stdout || verify_mode)
  177.       {
  178.         if(noexec)
  179.         {
  180.           printf("%s %s\n", verify_mode ? "VERIFY" : "EXTRACT",name);
  181.           if (afp == stdin)
  182.           {
  183.             int i = hdr->packed_size;
  184.             while(i--) fgetc(afp);
  185.           }
  186.         return;
  187.       }
  188.  
  189.       save_quiet = quiet;
  190.       save_verbose = verbose;
  191.       if(!quiet && output_to_stdout)
  192.       {
  193.         printf("::::::::\n%s\n::::::::\n", name);
  194.         quiet = TRUE;
  195.         verbose = FALSE;
  196.       }
  197.       else if(verify_mode)
  198.     {
  199.         quiet = FALSE;
  200.         verbose = TRUE;
  201.       }
  202.  
  203.       crc = decode_lzhuf(afp, stdout, hdr->original_size, hdr->packed_size, name, method);
  204.       quiet = save_quiet;
  205.       verbose = save_verbose;
  206.     }
  207.   else
  208.     {
  209.       if(!inquire_extract(name)) return;
  210.  
  211.       if(noexec)
  212.       {
  213.         if(afp == stdin)
  214.           {
  215.             int i = hdr->packed_size;
  216.             while(i--) fgetc(afp);
  217.           }
  218.         return;
  219.       }
  220.  
  221.       signal(SIGINT, interrupt);
  222.  
  223.       unlink (name);
  224.       errno = 0;
  225.       remove_extracting_file_when_interrupt = TRUE;
  226.       if((fp = open_with_make_path (name)) != NULL)
  227.     {
  228.         crc = decode_lzhuf(afp, fp, hdr->original_size, hdr->packed_size, name, method);
  229.       fclose (fp);
  230.       }
  231.       remove_extracting_file_when_interrupt = FALSE;
  232.       signal (SIGINT, SIG_DFL);
  233.  
  234.       if(!fp) return;
  235.     }
  236.  
  237.   errno = 0;
  238.   if(hdr->has_crc && crc != hdr->crc) error("CRC error", name);
  239.  
  240.   }
  241.   else if((hdr->unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_DIRECTORY)
  242.   {
  243.     if(!ignore_directory && !verify_mode)
  244.       {
  245.         if(noexec)
  246.         {
  247.           printf ("EXTRACT %s (directory)\n", name);
  248.           return;
  249.         }
  250.         /* NAME has trailing SLASH '/', (^_^) */
  251.         if(!output_to_stdout && !make_parent_path (name))
  252.           return;
  253.       }
  254.   }
  255.   else
  256.   {
  257.     error ("Unknown information", name);
  258.   }
  259.  
  260.   if(!output_to_stdout) adjust_info (name,hdr);
  261. }
  262.  
  263. /*----------------------------------------------------------------------*/
  264. /*            EXTRACT COMMAND MAIN                */
  265. /*----------------------------------------------------------------------*/
  266.  
  267. void cmd_extract()
  268. {
  269.   LzHeader hdr;
  270.   long pos;
  271.   FILE *afp;
  272.  
  273.   /* open archive file */
  274.   if((afp = open_old_archive ()) == NULL)
  275.     fatal_error (archive_name);
  276.   if(archive_is_msdos_sfx1 (archive_name))
  277.     skip_msdos_sfx1_code (afp);
  278.  
  279.   /* extract each files */
  280.   while(get_header (afp, &hdr))
  281.   {
  282.     if (need_file (hdr.name))
  283.       {
  284.         pos = ftell (afp);
  285.         extract_one (afp, &hdr);
  286.         fseek (afp, pos + hdr.packed_size, SEEK_SET);
  287.       }
  288.     else
  289.       {
  290.         if(afp != stdin)
  291.           fseek (afp, hdr.packed_size, SEEK_CUR);
  292.         else
  293.         {
  294.           int i = hdr.packed_size;
  295.           while(i--) fgetc(afp);
  296.         }
  297.       }
  298.   }
  299.  
  300.   /* close archive file */
  301.   fclose (afp);
  302.   return;
  303. }
  304.